import { App } from "../App";
import { Singleton } from "./Class";
import { EventConst } from "./EventConst";

export class CViewMgr extends Singleton<CViewMgr>{
    private _sceneLayout:cc.Node = null;
    private _viewLayout:cc.Node = null;
    private _maskLayout:cc.Node = null;
    private _curScene: cc.Component = null;
    private _activeView: cc.Component = null;
    private _curSceneFlag: string = '';
    private _canvasSize = cc.size(0,0);
    private _designSize = cc.size(0,0);
    constructor(){
        super();
    }

    protected onInit(scene:cc.Node,view:cc.Node,top:cc.Node,mask:cc.Node){
        this._sceneLayout = scene;
        this._viewLayout = view;
        this._maskLayout = mask;
        this._viewLayout.active = false;
        this._maskLayout.active = false;
        this._canvasSize = cc.view.getFrameSize();
        this._designSize = cc.view.getDesignResolutionSize();

        this._activeView = null;
        App.Event.on(EventConst.ENTRY_SCENE, this._entryScene, this);
        App.Event.on(EventConst.OPEN_VIEW, this._openView, this);
        App.Event.on(EventConst.CLOSE_VIEW, this._closeView, this);
        App.Event.on(EventConst.JUST_NODE_SIZE, this._justNodeSize, this);
    }

    private _entryScene(scene: string, entryCall?: () => void, ...args: any) {
        if (App.Util.isEmpty(scene)){
            console.error('viewMgr.entryScene is error.');
            return ;
        }
        let subs = scene.split(':')
        if (subs.length !== 2) {
            cc.error(`LayoutManager._entryScene(${scene}) is error./n eg:'name:login|hall|room'`);
            return;
        }

        //this.lblVersion.node.active = subs[0] === 'LoginScene';
        this._curSceneFlag === '' && (this._curSceneFlag = subs[1]);
        let path = `prefab/scene/${subs[0]}`;
        App.Res.loadRes(`${path}:${subs[1]}`,cc.Prefab,(prefab:cc.Prefab)=>{
            this._addLayout(cc.instantiate(prefab), false, subs[0],()=>{
                // @ts-ignore
                this._initParam(this._curScene.init,args[0]);
                entryCall && entryCall();
                if (this._curSceneFlag !== subs[1]) {
                    this._curSceneFlag = subs[1];
                }
            });
        });
    }

    private _openView(name: string, openCall?: () => void, ...args: any) {
        if (App.Util.isEmpty(name)){
            console.error('viewMgr.openView is error.');
            return ;
        }
        let subs = name.split(':')
        if (subs.length !== 2) {
            cc.error(`LayoutManager._openView(${name}) is error./n eg:'name:login|hall|room'`);
            return;
        }

        console.time('openView');
        let key = subs[1];
        let path = `prefab/view/${subs[0]}`;
        App.Res.loadRes(`${path}:${key}`,cc.Prefab,(prefab:cc.Prefab)=>{
            this._addLayout(cc.instantiate(prefab), true, subs[0],()=>{
                // @ts-ignore
                this._initParam(this._activeView && this._activeView.init,args[0]);
                openCall && openCall();
                console.timeEnd('openView');
            });
        });
    }

    private _closeView(view: cc.Node | cc.Component, closeCall?: () => void, ...args: any) {
        if (view instanceof cc.Component) {
            view = view.node;
        }
        
        this._aniView(false, view, () => {
            this._activeView = null;
            closeCall && closeCall();
        });

    }

    private _addLayout(node: cc.Node, isWidget: boolean, cls?: string, call?: ()=>void) {
        if (!node) return ;
        this._justNodeSize(node);
        if (isWidget) {
            if (!this._viewLayout.active) {
                this._activeView = node.getComponent(cls);
                this._aniView(true, node,call);
            }
        } else {
            this._sceneLayout.addChild(node);
            if (this._curScene) {
                App.Event.offAll(this._curScene);
                // @ts-ignore
                this._curScene.release && this._curScene.release();
                this._curScene.destroy();
            }
            this._curScene = node.getComponent(cls);
            call && call();
        }
    }

    private _aniView(isShow: boolean, node: cc.Node, call?: () => void) {
        if (!node) return ;

        let nodeScale:number = 1;
        if (isShow){
            node.scale = nodeScale;
            this._viewLayout.active = true;
            this._viewLayout.opacity = 0;
            this._viewLayout.addChild(node);
        }

        // 播放弹窗主体动画
        cc.tween(this._viewLayout)
        .to(0.02, {opacity: isShow ? 255 : 0}, { easing: isShow ? 'backIn' : 'backOut' })
        .call(() => {
            if (!isShow) {
                App.Event.offAll(node);
                node.destroy();
                this._viewLayout.active = false;
                this._viewLayout.opacity = 255;
                this._viewLayout.removeChild(node);
            }
            call && call();
        }).start();
    }

    private _justNodeSize(node:cc.Node|cc.Component){
        if (!node) {
            console.warn(`ViewMgr._justNodeSize() error.`);
            return ;
        }
        if (node instanceof cc.Component) node = node.node;
        const canvas = cc.Canvas.instance;
        if (canvas.fitHeight && !canvas.fitWidth) { 
            // 竖屏应用，宽对齐
            node.width = this._canvasSize.width;
        } else if (canvas.fitWidth && !canvas.fitHeight){ 
            // 横屏应用，高对齐
            node.height = this._canvasSize.height;
        }
    }

    private _initParam(fun:Function,params:any[]){
        if (!fun) return ;
        (!params || params.length < 1) ? fun.call(this._activeView) : fun.call(this._activeView,params[0],params[1],params[2],params[3],params[4]);
    };
}

const ViewMgr:CViewMgr = CViewMgr.getInstance<CViewMgr>(CViewMgr);
export default ViewMgr; 